<template>
  <div class="g-full-height chart-box" :class="className"></div>
</template>
<script>
import echarts from "echarts";
import {
  isArray,
  isPlainObject,
  extend,
  debounce,
  num2Unit,
} from "../../untill/fn/index.js";
import config from "./config";
let C = {};

export default {
  name: "chart",
  props: {
    options: {
      type: Object,
      default: () => ({}),
    },
    unit: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      chart: undefined,
      className: Math.random() + new Date().getTime().toString(),
      chartOptions: {},
      optionsWatch: debounce(() => {
        //ktfn后面得单独引入
        this.createOptioins();
        if (!this.chartOptions) {
          return;
        }
        this.chart.setOption(this.chartOptions, true, true);
        setTimeout(() => {
          this.reRender();
        }, 500);
      }),
      //重绘
      reCalc: debounce(() => {
        //ktfn后面得单独引入
        this.reRender();
      }, 1800),
    };
  },
  created() {
    //生成配置
    this.createOptions();
  },
  mounted() {
    this.createChart();
    this.bindResize();
  },
  methods: {
    //生成配置
    createOptions() {
      if (
        !isPlainObject(this.options) ||
        Object.keys(this.options).length === 0
      ) {
        return;
      }
      //获取配置文件
      C = this.$store.state.chartTheme === "white" ? config.white : config.dark;
      this.chartOptions = extend({}, this.options);
      //转换格式
      this.formatter(this.chartOptions);
      //获取series
      this.createSeries();
      //获取Axis
      this.createXAxis();
      this.createYAxis();
      //获取legend
      this.createLegend();
      //获取grid
      this.createGrid();
      //获取tooltip
      this.createTooltip();
      //获取textStyle
      this.createTextStyle();
      //设置默认dataZoom
      this.setDataZoom();
    },
    //转换格式
    formatter(options) {
      if (isPlainObject(options.xAxis)) {
        options.xAxis = [options.xAxis];
      }
      if (isPlainObject(options.yAxis)) {
        options.yAxis = [options.yAxis];
      }
      if (isPlainObject(options.series)) {
        options.series = [options.series];
      }
      if (isPlainObject(options.legend)) {
        options.legend = [options.legend];
      }
      if (isPlainObject(options.grid)) {
        options.grid = [options.grid];
      }
      if (isPlainObject(options.tooltip)) {
        options.tooltip = [options.tooltip];
      }
    },
    //获取主题
    getTheme(type) {
      let ktTheme = this.options.ktTheme || this.options.ktGTheme;
      if (!ktTheme) return {};
      let theme = C.theme[ktTheme];
      if (!theme) return;
      //x轴
      if (theme.xAxis && type === "xAxis") {
        return theme.xAxis;
      }
      //y轴
      else if (theme.series && type === "series") {
        return theme.series;
      }
      //textStyle
      else if (theme.textStyle && type === "textStyle") {
        return theme.textStyle;
      }
      //tooltip
      else if (theme.tooltip && type === "tooltip") {
        return theme.tooltip;
      }
    },
    //生成series
    createSeries() {
      let series = this.chartOptions.series;
      if (!isArray(series)) {
        return;
      }
      //去掉不是对象的属性
      series = series.filter((v) => isPlainObject(v));
      let config;
      //获取图表类型,逗号隔开
      let chartTypes = series.map((v) => v.type).join(",");
      this.chartOptions.series = series.map((v, i) => {
        config = {};
        //加载默认series
        config = extend(config, C.defaultSeries[v.type]);

        if (v.type === "pie") {
          if (v.data.length === 2) {
            let colors = ["#0094ff", "#ed6d00"];
            config = extend(config, {
              itemStyle: {
                color: (p) => colors[p.dataIndex],
              },
            });
          } else if (v.data.length > 13) {
            let colors = [
              "#2e71aa",
              "#3e93db",
              "#4eb0e8",
              "#73c1ed",
              "#429293",
              "#4dacac",
              "#428c36",
              "#50a343",
              "#79b56c",
              "#a3cfa3",
              "#8b8629",
              "#dab83d",
              "#fada4b",
              "#faef78",
              "#c17429",
              "#e59234",
              "#eeb870",
              "#f5dda8",
              "#ae232f",
              "#d33c3f",
              "#d7697c",
              "#e5a6b0",
              "#902074",
              "#b02c89",
              "#c384af",
              "#edcbdc",
            ];
            config = extend(config, {
              itemStyle: {
                color: (p) => colors[p.dataIndex],
              },
            });
          }
          config = extend(config, {
            label: {
              formatter: `{b}:{d}%`,
              lineHeight: 16,
            },
          });
        }
        //加载默认series主题配置
        if (!v.ktTheme) {
          let themeConfig = C.mutipleChartSeriesThemeConfig[chartTypes];
          if (
            themeConfig &&
            themeConfig[i] &&
            C.seriesTheme[v.type] &&
            C.seriesTheme[v.type][themeConfig[i]]
          ) {
            config = extend(config, C.seriesTheme[v.type][themeConfig[i]]);
          }
        }
        //加载主题
        config = extend(config, this.getTheme("series"));
        //加载series主题
        if (
          v.ktTheme &&
          C.seriesTheme[v.type] &&
          C.seriesTheme[v.type][v.ktTheme]
        ) {
          config = extend(config, C.seriesTheme[v.type][v.ktTheme]);
        }
        //加载用户传入数据
        config = extend(config, v);
        return config;
      });
    },
    //生成xAxis
    createXAxis() {
      let xAxis = this.chartOptions.xAxis;
      if (!isArray(xAxis)) {
        return;
      }
      //去掉不是对象的属性
      // xAxis = xAxis.filter((v) => isPlainObject(v));
      this.chartOptions.xAxis = xAxis.map((v) => {
        this.setXAxisLabel(v);
        return extend(C.defaultConfig.xAxis, this.getTheme("xAxis"), v);
      });
    },
    //生成yAxis
    createYAxis() {
      let yAxis = this.chartOptions.yAxis;
      if (!isArray(yAxis)) {
        return;
      }
      //去掉不是对象的属性
      yAxis = yAxis.filter((v) => isPlainObject(v));
      this.chartOptions.yAxis = yAxis.map((v) => {
        return extend(C.defaultConfig.yAxis, this.getTheme("yAxis"), v);
      });
    },
    //生成legend
    createLegend() {
      let config = extend(C.defaultConfig.legend, this.getTheme("legend"));
      //如果是饼状图
      let series = this.chartOptions.series,
        isPie = true;
      for (let i = 0; i < series.length; i++) {
        if (series[i].type !== "pie") {
          isPie = false;
          break;
        }
      }
      if (isPie) {
        config = extend(config, {
          type: "scroll",
          bottom: 0,
          formatter: (name) => {
            let index = series[0].data.map((v) => v.name).indexOf(name);
            return (
              name +
              ":" +
              num2Unit(series[0].data[index].value, 3) +
              (this.options.ktUnit ? this.options.ktUnit : this.unit)
            );
          },
        });
      }
      if (!this.chartOptions.legend) {
        this.chartOptions.legend = [{}];
      }
      if (isArray(this.chartOptions.legend)) {
        //去掉不是对象的属性
        this.chartOptions.legend = this.chartOptions.legend
          .filter((v) => isPlainObject(v))
          .map((v) => {
            return extend(config, v);
          });
      }
    },
    //生成grid
    createGrid() {
      let grid = this.chartOptions.grid;
      if (!grid) {
        this.chartOptions.grid = [
          extend(C.defaultConfig.grid, this.getTheme("grid")),
        ];
      }
      if (isArray(grid)) {
        //去掉不是对象的属性
        grid = grid.filter((v) => isPlainObject(v));
        this.chartOptions.grid = grid.map((v) => {
          return extend(C.defaultConfig.grid, this.getTheme("grid"), v);
        });
      }
    },
    //生成tooltip
    createTooltip() {
      let series = this.chartOptions.series,
        typeTooltip = {};
      series.forEach((v) => {
        if (v.type === "pie") {
          if (!v.tooltip) {
            v.tooltip = {
              formatter: (p) =>
                `${p.marker}  ${p.name}:${num2Unit(p.value, 3)} ${
                  this.options.ktUnit ? this.options.ktUnit : this.unit
                }(${p.percent}%)`,
            };
          }
          typeTooltip = {
            trigger: "item",
          };
        } else if (v.type === "bar" || v.type === "line") {
          typeTooltip = {
            trigger: "axis",
          };
        }
      });

      let tooltip = this.chartOptions.tooltip;
      if (!tooltip) {
        this.chartOptions.tooltip = [
          extend(
            C.defaultConfig.tooltip,
            typeTooltip,
            this.getTheme("tooltip")
          ),
        ];
      }
      if (isArray(tooltip)) {
        //去掉不是对象的属性
        tooltip = tooltip.filter((v) => isPlainObject(v));
        this.chartOptions.tooltip = tooltip.map((v) => {
          return extend(
            C.defaultConfig.tooltip,
            typeTooltip,
            this.getTheme("tooltip"),
            v
          );
        });
      }
    },
    //生成textStyle
    createTextStyle() {
      this.chartOptions.textStyle = extend(
        this.getTheme("textStyle"),
        this.chartOptions.textStyle
      );
    },
    //设置默认dataZoom
    setDataZoom() {
      //限制页面默认最多的展示条数,超出限制则出现dataZoom
      if (this.options.ktLimitShowNum && !this.options.dataZoom) {
        //获取坐标轴数据条数(默认取第一条轴)
        let axisDataNum = this.chartOptions.xAxis[0].data.length;
        if (this.options.ktLimitShowNum >= axisDataNum) {
          return;
        }
        let startValue = 0,endValue = this.options.ktLimitShowNum - 1;
        if (this.options.ktDataZoomLocation === "end") {
          startValue = axisDataNum - this.options.ktLimitShowNum;
          endValue = axisDataNum - 1;
        }
        this.chartOptions.dataZoom = [
          {
            ...C.dataZoom,
            startValue,
            endValue,
          },
          {
            type: "inside",
          },
        ];
      }
    },
    //设置x轴刻度标签
    setXAxisLabel(xAxis) {
      //限制每行最多显示字符,超出换行
      if (
        xAxis.axisLabel &&
        xAxis.axisLabel.ktRowNum &&
        !xAxis.axisLabel.formatter
      ) {
        let rowNum = xAxis.axisLabel.ktRowNum;
        xAxis.axisLabel.formatter = (val) => {
          let arr = val.split("");
          for (let i = rowNum - 1; i < arr.length; i += rowNum) {
            arr[i] += "\n";
          }
          return arr.join("");
        };
      }
    },
    //生成图
    createChart() {
      this.chart = echarts.init(
        document.getElementsByClassName(this.className)[0]
      );
      this.chart.setOption(this.chartOptions);
    },
    //重绘
    reRender() {
      this.chart.resize();
    },
    //窗口大小改变
    bindResize() {
      window.addEventListener("resize", this.reCalc);
    },
    unbindResize() {
      window.removeEventListener("resize", this.reCalc);
    },
  },
  watch: {
    options: {
      handler() {
        this.optionsWatch();
      },
      deep: true,
    },
    "$store.state.chartTheme": {
      handler() {
        this.optionsWatch();
      },
      deep: true,
    },
  },
  beforeDestroy() {
    this.unbindResize();
  },
};
</script>
<style scoped lang="scss">
.chart-box {
  width: 100%;
  height: 100%;
}
</style>
